package com.blacktech.dbu.core.util;

import com.blacktech.dbu.core.annotation.Searchable;
import jakarta.persistence.criteria.*;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 搜索字段工具类
 * 用于处理实体类中带有@Searchable注解的字段
 *
 * @author Yanyunsong
 */
@Component
public class SearchableFieldsUtils {

    /**
     * 缓存类的搜索字段信息
     */
    private static final Map<Class<?>, List<FieldInfo>> SEARCHABLE_FIELDS_CACHE = new ConcurrentHashMap<>();

    /**
     * 字段信息内部类
     */
    public static class FieldInfo {
        private final String fieldName;
        private final String displayName;
        private final boolean caseSensitive;
        private final int priority;

        public FieldInfo(String fieldName, String displayName, boolean caseSensitive, int priority) {
            this.fieldName = fieldName;
            this.displayName = displayName;
            this.caseSensitive = caseSensitive;
            this.priority = priority;
        }

        public String getFieldName() {
            return fieldName;
        }

        public String getDisplayName() {
            return displayName;
        }

        public boolean isCaseSensitive() {
            return caseSensitive;
        }

        public int getPriority() {
            return priority;
        }
    }

    /**
     * 获取指定类中所有可搜索的字段
     *
     * @param entityClass 实体类
     * @return 可搜索字段列表
     */
    public List<FieldInfo> getSearchableFields(Class<?> entityClass) {
        return SEARCHABLE_FIELDS_CACHE.computeIfAbsent(entityClass, this::extractSearchableFields);
    }

    /**
     * 从实体类中提取可搜索字段
     *
     * @param entityClass 实体类
     * @return 可搜索字段列表
     */
    private List<FieldInfo> extractSearchableFields(Class<?> entityClass) {
        List<FieldInfo> fieldInfos = new ArrayList<>();

        // 获取当前类及其父类的所有字段
        Class<?> currentClass = entityClass;
        while (currentClass != null && currentClass != Object.class) {
            Field[] fields = currentClass.getDeclaredFields();

            for (Field field : fields) {
                Searchable searchableAnnotation = field.getAnnotation(Searchable.class);
                if (searchableAnnotation != null) {
                    String fieldName = field.getName();
                    String displayName = searchableAnnotation.value().isEmpty() ? fieldName : searchableAnnotation.value();
                    boolean caseSensitive = searchableAnnotation.caseSensitive();
                    int priority = searchableAnnotation.priority();

                    fieldInfos.add(new FieldInfo(fieldName, displayName, caseSensitive, priority));
                }
            }

            currentClass = currentClass.getSuperclass();
        }

        // 按优先级排序
        fieldInfos.sort(Comparator.comparingInt(FieldInfo::getPriority));

        return fieldInfos;
    }

    /**
     * 构建关键词搜索的Predicate
     *
     * @param root            查询根对象
     * @param criteriaQuery   查询对象
     * @param criteriaBuilder 条件构建器
     * @param entityClass     实体类
     * @param keyword         关键词
     * @return 搜索条件
     */
    public Predicate buildKeywordPredicate(Root<?> root, CriteriaQuery<?> criteriaQuery,
                                         CriteriaBuilder criteriaBuilder, Class<?> entityClass, String keyword) {
        if (keyword == null || keyword.trim().isEmpty()) {
            return criteriaBuilder.conjunction();
        }

        List<FieldInfo> searchableFields = getSearchableFields(entityClass);
        if (searchableFields.isEmpty()) {
            return criteriaBuilder.conjunction();
        }

        List<Predicate> predicates = new ArrayList<>();
        String searchKeyword = keyword.trim();

        for (FieldInfo fieldInfo : searchableFields) {
            String fieldName = fieldInfo.getFieldName();

            try {
                // 创建字段路径表达式
                Expression<String> fieldExpression = root.get(fieldName).as(String.class);

                // 构建模糊匹配条件
                if (fieldInfo.isCaseSensitive()) {
                    predicates.add(criteriaBuilder.like(fieldExpression, "%" + searchKeyword + "%"));
                } else {
                    predicates.add(criteriaBuilder.like(criteriaBuilder.lower(fieldExpression), "%" + searchKeyword.toLowerCase() + "%"));
                }
            } catch (IllegalArgumentException e) {
                // 如果字段类型无法转换为String，跳过该字段
                continue;
            }
        }

        return predicates.isEmpty() ? criteriaBuilder.conjunction()
                                   : criteriaBuilder.or(predicates.toArray(new Predicate[0]));
    }

    /**
     * 清除缓存
     */
    public void clearCache() {
        SEARCHABLE_FIELDS_CACHE.clear();
    }

    /**
     * 清除指定类的缓存
     *
     * @param entityClass 实体类
     */
    public void clearCache(Class<?> entityClass) {
        SEARCHABLE_FIELDS_CACHE.remove(entityClass);
    }
}